package com.engine.game;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;

import aurelienribon.tweenengine.TweenManager;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.interpolation.game.Interpolator;
import com.level.game.Level;
import com.physics.game.PhysicsWorld;
import com.render.game.RenderType;
import com.render.game.Renderer;
import com.render.game.Stage;

    public class GameState {
    	
	
    	
    public GameState(GameEngine engine, Interpolator interpolator, Level level) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
    	this.mapOfGameObjects = new HashMap<String, GameEntity>();
    	this.setEngine(engine);
    	this.setInterpolator(interpolator);
    	
    	
    	this.interpolator.registerEntities();
    	
        this.Graveyard = new ArrayList<String>();
    	
        this.setCurrentLevel(level);
        
    	this.renderer = new Renderer(this.currentLevel.getWorldMax(), new Vector2(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()));
    	
    	
    	
    	
    	this.currentLevel.load(this);
    
    	
    	
    	
    }
    	
    	
    	
	private HashMap<String, GameEntity> mapOfGameObjects;

	private GameEngine engine;
	
	private Interpolator interpolator;
	
	private Renderer renderer;
	
	private PhysicsWorld physicsWorld; 

	private Level currentLevel;
	
	
	
	private ArrayList<String> Graveyard;
	

	public void setEngine(GameEngine engine) {
		this.engine = engine;
	}

	public void setInterpolator(Interpolator interpolator) {
		this.interpolator = interpolator;
	}
	
	
	
	public void pushObjectToRenderer(String name, RenderType type, int index, int stage){
		this.renderer.pushObjectToStage(name, type, index, stage);
	}
	
	public void pushObjectToRenderer(String name, RenderType type, int stage){
		this.renderer.pushObjectToStage(name, type, stage);

	}
	
	public void deleteObjectFromRenderer(String name, RenderType type, int stage){
		this.renderer.deleteObjectFromStage(name, type, stage);
	}
	
	
	public void pushEvent(Event event){
		
		
		this.engine.pushEvent(event);
	}

	
	public void sendToGraveyard(String name){
		this.Graveyard.add(name);
	}
	
	public PhysicsWorld getPhysicsWorld(){
		return this.physicsWorld;
	}
	
	public void setPhysicsWorld(PhysicsWorld physicsWorld) {
		this.physicsWorld = physicsWorld;
	}
	
	public TweenManager getTweenManager(){
		return this.engine.getTweenManager();
	}
	
	
	public Stage getStage(int index){
		return this.renderer.getStage(index);
	}
	
	public int getStageID(String name){
		return this.mapOfGameObjects.get(name).getStageID();
	}
	
	public void receiveEvent(Event event){
		
		
		
		if(event.getReceiver().equals("RENDERER")){
			this.renderer.receiveMessage(event);
		}
		
		if(this.mapOfGameObjects.get(event.getReceiver()) == null){
			System.out.println("bad");
			System.out.println(event.getReceiver());
			System.out.println(event.getMessage());
		}
		
		this.mapOfGameObjects.get(event.getReceiver()).receiveMessage(event);
		
		
		
	}
	
    public void receiveBroadcastEvent(Event event){
    	
    	for(String s : this.mapOfGameObjects.keySet()){
    		
    		this.mapOfGameObjects.get(s).receiveMessage(event);
    		
    		this.renderer.receiveMessage(event);
    		
    	}
    	
		
	}

	public void update() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
		
		for(String key : mapOfGameObjects.keySet()){
			
			if(!this.mapOfGameObjects.get(key).getIsDead()){
				
				this.mapOfGameObjects.get(key).update();
				
			}
		}
		
		this.renderer.update();
		
		this.clearGraveyard();
	}
	
	public void clearGraveyard(){
		for(String s : this.Graveyard){
			this.removeObject(s);
		}
		
		this.Graveyard.clear();
	}
	
	
	public void render(float alpha){
		this.renderer.render(this.mapOfGameObjects, alpha);
	}
	
	public void resize(int width, int height){
		this.renderer.resize(width, height);
		
	//	this.renderer.changeWorldMax(new Vector2(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()));
	}
	
	public Vector2 getWorldCoordinates(Vector2 v){
		return this.renderer.getWorldCoordinates(v);
    }

	
	public void addStageToRenderer(Stage stage){
		this.renderer.addStage(stage);
	}
	
	public GameEntity getGameObject(String name){
		return this.mapOfGameObjects.get(name);
	}
	
	
	public void addGameObject(GameObject obj){
		this.mapOfGameObjects.put(obj.name, obj);
	}


	public void removeObject(String name){
		this.mapOfGameObjects.get(name).dispose();
		this.mapOfGameObjects.remove(name);
	}
	
	public void removeAllObjects(){
		for(String key : this.mapOfGameObjects.keySet()){
			this.mapOfGameObjects.get(key).dispose();
			
		}
		
		this.mapOfGameObjects.clear();
	}


	public void setCurrentLevel(Level level) {
		this.currentLevel = level;
	}
	
	public void changeLevel(Level level) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
		this.removeAllObjects();
		this.setCurrentLevel(level);
		this.currentLevel.load(this);
	}


	public void dispose(){
		
		
		this.clearGraveyard();
		
		this.removeAllObjects();
		
		this.Graveyard = null;
		this.mapOfGameObjects = null;
		this.interpolator = null;
		
		this.renderer.dispose();
		
		this.physicsWorld.dispose();
	}

	


	
}
